package org.malred.hospital.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.malred.hospital.common.BaseContext;
import org.malred.hospital.common.R;

import org.malred.hospital.dto.OrderInsertDto;
import org.malred.hospital.dto.OrderListDateDto;
import org.malred.hospital.dto.OrderListDto;
import org.malred.hospital.dto.OrderUpdateDto;
import org.malred.hospital.entity.*;
import org.malred.hospital.entity.TbOrder;
import org.malred.hospital.service.*;
import org.malred.hospital.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
//@CrossOrigin()
@RestController
@RequestMapping("/order")
public class OrderController extends BaseController<TbOrder> {
    @Autowired
    private OrderService service;
    @Autowired
    private StudentService studentService;
    @Autowired
    private DoctorService doctorService;
    @Autowired
    private MedicineHistoryService medicineHistoryService;
    @Autowired
    private HistoryService historyService;

    @Override
    public R<List<TbOrder>> findAll() {
        return null;
    }

    @GetMapping("/dto/findAll")
    public R<List<OrderListDto>> findAllDto() {
        List<TbOrder> list = service.list();
//        log.info("order list: {}", list);
        List<OrderListDto> collect = list.stream().map(o -> {
            TbStudent student = studentService.getById(o.getStudentId());
            TbDoctor doctor = doctorService.getById(o.getDoctorId());

            OrderListDto dto = new OrderListDto();
            dto.setId(o.getId());
            dto.setDoctor(doctor);
            dto.setStudent(student);
            String date = "";
            try {
                date = DateUtils.DateToString(
                        new SimpleDateFormat("yyyy-MM-dd"),
                        DateUtils.LocalDateTimeToDate(o.getCreateTime())
                );
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            dto.setCreateTime(date);
            return dto;
        }).collect(Collectors.toList());
        return R.success(collect);
    }

    @Override
    public R<TbOrder> findById(@PathVariable Long id) {
        return R.success(service.getById(id));
    }

//    @GetMapping("/dto/{id}")
//    public R<TbOrder> findByIdDto(@PathVariable Long id) {
//        return R.success(service.getById(id));
//    }

    @GetMapping("/find/name/{name}")
    public R<List<OrderListDto>> findByName(@PathVariable String name) {
        // set去重
        Set<TbOrder> list = new HashSet<>();

        // 获取所有包含studentid或doctorid或都有的订单
        LambdaQueryWrapper<TbStudent> sqw = new LambdaQueryWrapper<>();
        sqw.like(TbStudent::getName, name);
        List<TbStudent> slist = studentService.list(sqw);

        if (slist != null && !slist.isEmpty()) {
            for (TbStudent s : slist) {
                LambdaQueryWrapper<TbOrder> qw = new LambdaQueryWrapper<>();
                qw.eq(TbOrder::getStudentId, s.getId());
                list.addAll(service.list(qw));
            }
        }

        LambdaQueryWrapper<TbDoctor> dqw = new LambdaQueryWrapper<>();
        dqw.like(TbDoctor::getName, name);
        List<TbDoctor> dlist = doctorService.list(dqw);
        if (dlist != null && !dlist.isEmpty()) {
            for (TbDoctor d : dlist) {
                LambdaQueryWrapper<TbOrder> qw = new LambdaQueryWrapper<>();
                qw.eq(TbOrder::getDoctorId, d.getId());
                list.addAll(service.list(qw));
            }
        }

        ArrayList<TbOrder> orders = new ArrayList<>(list);
        List<OrderListDto> dtos = orders.stream().map(o -> {
            TbStudent s = studentService.getById(o.getStudentId());
            TbDoctor d = doctorService.getById(o.getDoctorId());

            OrderListDto dto = new OrderListDto();
            dto.setStudent(s);
            dto.setDoctor(d);
            dto.setCreateTime(String.valueOf(o.getCreateTime()));
            return dto;
        }).collect(Collectors.toList());
        return R.success(dtos);
    }

    @GetMapping("/find/{start}/{end}")
    public R<OrderListDateDto> findInDate(@PathVariable String start,
                                          @PathVariable String end) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        LambdaQueryWrapper<TbOrder> qw = new LambdaQueryWrapper<>();
        qw.ge(TbOrder::getCreateTime, DateUtils.StringToDate(format, start));
        qw.le(TbOrder::getCreateTime, DateUtils.StringToDate(format, end));
        List<TbOrder> list = service.list(qw);

        LambdaQueryWrapper<TbDoctor> dqw = new LambdaQueryWrapper<>();
        dqw.ge(TbDoctor::getCreateTime, DateUtils.StringToDate(format, start));
        dqw.le(TbDoctor::getCreateTime, DateUtils.StringToDate(format, end));
        List<TbDoctor> dlist = doctorService.list(dqw);
        List<TbDoctor> doctors = dlist.stream().map(d -> {
            TbDoctor doctor = new TbDoctor();
            doctor.setNumber(0L);
            doctor.setName(d.getName());
            for (TbOrder o : list) {
                if (Objects.equals(o.getDoctorId(), d.getId())) {
                    doctor.setNumber(doctor.getNumber() + 1);
                }
            }
            return doctor;
        }).collect(Collectors.toList());

        LambdaQueryWrapper<TbStudent> sqw = new LambdaQueryWrapper<>();
        sqw.ge(TbStudent::getCreateTime, DateUtils.StringToDate(format, start));
        sqw.le(TbStudent::getCreateTime, DateUtils.StringToDate(format, end));
        List<TbStudent> slist = studentService.list(sqw);
        List<TbStudent> students = slist.stream().map(s -> {
            TbStudent student = new TbStudent();
            student.setNumber(0L);
            student.setName(s.getName());
            for (TbOrder o : list) {
                if (Objects.equals(o.getStudentId(), s.getId())) {
                    student.setNumber(student.getNumber() + 1);
                }
            }
            return student;
        }).collect(Collectors.toList());

        OrderListDateDto dto = new OrderListDateDto();
        dto.setDoctors(doctors);
        dto.setStudents(students);
        dto.setOrders(list);

        return R.success(dto);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/page")
    public R<List<OrderListDto>> page(int page, int size) {
        //分页构造器
        Page<TbOrder> pageInfo = new Page<>(page, size);
        //条件构造器
        LambdaQueryWrapper<TbOrder> queryWrapper = new LambdaQueryWrapper<>();
        //添加排序条件，根据sort进行排序
        queryWrapper.orderByAsc(TbOrder::getCreateTime);

        //分页查询
        service.page(pageInfo, queryWrapper);
        List<TbOrder> orders = pageInfo.getRecords();

        List<OrderListDto> collect = orders.stream().map(o -> {
            TbStudent student = studentService.getById(o.getStudentId());
            TbDoctor doctor = doctorService.getById(o.getDoctorId());

            OrderListDto dto = new OrderListDto();
            dto.setId(o.getId());
            dto.setDoctor(doctor);
            dto.setStudent(student);
            String date = "";
            try {
                date = DateUtils.DateToString(
                        new SimpleDateFormat("yyyy-MM-dd"),
                        DateUtils.LocalDateTimeToDate(o.getCreateTime())
                );
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            dto.setCreateTime(date);
            return dto;
        }).collect(Collectors.toList());

        return R.success(collect);
    }

    /**
     * 分页获取某医生的预约记录
     *
     * @param page
     * @param size
     * @param did
     * @return
     */
    @GetMapping("/page-did")
    public R<List<OrderListDto>> pagedid(int page, int size, int did) {
        //分页构造器
        Page<TbOrder> pageInfo = new Page<>(page, size);
        //条件构造器
        LambdaQueryWrapper<TbOrder> queryWrapper = new LambdaQueryWrapper<>();
        //添加排序条件，根据sort进行排序
        queryWrapper.orderByAsc(TbOrder::getCreateTime);
        queryWrapper.eq(TbOrder::getDoctorId, did);
        queryWrapper.ne(TbOrder::getStatus, 2L);

        //分页查询
        service.page(pageInfo, queryWrapper);
        List<TbOrder> orders = pageInfo.getRecords();

        List<OrderListDto> collect = orders.stream().map(o -> {
            TbStudent student = studentService.getById(o.getStudentId());
            TbDoctor doctor = doctorService.getById(o.getDoctorId());

            OrderListDto dto = new OrderListDto();
            dto.setId(o.getId());
            dto.setDoctor(doctor);
            dto.setStudent(student);
            dto.setStatus(o.getStatus());
            String date = "";
            try {
                date = DateUtils.DateToString(
                        new SimpleDateFormat("yyyy-MM-dd"),
                        DateUtils.LocalDateTimeToDate(o.getCreateTime())
                );
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            dto.setCreateTime(date);
            return dto;
        }).collect(Collectors.toList());

        return R.success(collect);
    }

    @GetMapping("/count")
    public R<Integer> count() {
        return R.success(service.count());
    }

    @Override
    public R<TbOrder> insert(@RequestBody TbOrder dto) {
        return null;
    }

    @PostMapping("/dto/save")
    public R<TbOrder> insertDto(@RequestBody OrderInsertDto dto) {
        if (studentService.getById(dto.getStudentId()) == null) {
            return R.error("没有该学生!");
        }
        if (doctorService.getById(dto.getDoctorId()) == null) {
            return R.error("没有该医生!");
        }

        TbOrder order = new TbOrder();
        order.setDoctorId(dto.getDoctorId());
        order.setStudentId(dto.getStudentId());
        service.save(order);
        return R.success(order);
    }

    @Override
    public R<TbOrder> update(@RequestBody TbOrder dto) {
        return null;
    }

    /**
     * 修改预订单
     *
     * @param dto
     * @return
     * @throws ParseException
     */
    @PutMapping("/dto/save")
    public R<TbOrder> updateDto(@RequestBody OrderUpdateDto dto) throws ParseException {
        TbOrder order = new TbOrder();
        order.setId(dto.getId());

        if (studentService.getById(dto.getStudentId()) == null) {
            return R.error("没有该学生!");
        }
        if (doctorService.getById(dto.getDoctorId()) == null) {
            return R.error("没有该医生!");
        }

        order.setDoctorId(dto.getDoctorId());
        order.setStudentId(dto.getStudentId());
        if (dto.getCreateTime() != null) {
            order.setCreateTime(
                    DateUtils.DateToLocalDateTime(
                            DateUtils.StringToDate(
                                    new SimpleDateFormat("yyyy-MM-dd"),
                                    dto.getCreateTime()
                            )
                    )
            );
        }

        service.saveOrUpdate(order);
        return R.success(order);
    }

    /**
     * 修改order状态为 1-已就诊(叫号)
     *
     * @param dto
     * @return
     * @throws ParseException
     */
    @PutMapping("/dto/status")
    public R<TbOrder> updateDtoStatus(@RequestBody OrderUpdateDto dto) throws ParseException {
        TbOrder order = new TbOrder();
        order.setId(dto.getId());

        if (studentService.getById(dto.getStudentId()) == null) {
            return R.error("没有该学生!");
        }
        if (doctorService.getById(dto.getDoctorId()) == null) {
            return R.error("没有该医生!");
        }

        order.setDoctorId(dto.getDoctorId());
        // 医生看病数+1
        TbDoctor d = doctorService.getById(dto.getDoctorId());
        d.setNumber(d.getNumber() + 1);
        doctorService.saveOrUpdate(d);

        order.setStudentId(dto.getStudentId());
        // 学生就诊数+1
        TbStudent s = studentService.getById(dto.getStudentId());
        s.setNumber(s.getNumber() + 1);
        studentService.saveOrUpdate(s);

        order.setStatus(dto.getStatus());

        service.saveOrUpdate(order);

        // 创建开药单记录
        TbMedicineHistory mh = new TbMedicineHistory();
        mh.setStudentId(order.getStudentId());
        mh.setDoctorId(order.getDoctorId());
        mh.setStatus(0L);
        medicineHistoryService.save(mh);

        // 创建看病记录
        TbHistory h = new TbHistory();
        h.setOrderId(order.getId());
        h.setStudentId(order.getStudentId());
        h.setDoctorId(order.getDoctorId());
        h.setMedicineHistoryId(mh.getId());
        historyService.save(h);

        order.setHistoryId(h.getId());
        service.saveOrUpdate(order);

        mh.setHistoryId(h.getId());
        medicineHistoryService.saveOrUpdate(mh);

        return R.success(order);
    }

    @Override
    public R<TbOrder> delete(@PathVariable Long id) {
        if (service.removeById(id)) {
            return R.success(null);
        } else {
            return R.error("删除 [Order] 失败");
        }
    }
}
